package jmine.tec.aop.log;

import java.lang.reflect.Method;
import java.util.Arrays;

import jmine.tec.proxy.chain.ChainElement;
import jmine.tec.proxy.chain.InvocationChain;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Loga a invocacao de todos os metodos, se o LogLevel do commons-logging eh DEBUG
 * 
 * @author takeshi
 */
public class LogInvocationChainElement implements ChainElement {

    private final Log logger = LogFactory.getLog(this.getClass());

    private final boolean log = logger.isDebugEnabled();

    /**
     * {@inheritDoc}
     */
    public Object aroundInvoke(InvocationChain chain) throws Throwable {
        if (log) {
            logger.debug(formatMethod(chain.getInvokingMethod()) + " -> " + Arrays.toString(chain.getParams()));
        }
        return chain.proceed();
    }

    /**
     * Formata um metodo, tirando nomes de pacotes
     * 
     * @param method the {@link Method}
     * @return {@link String}
     */
    public static String formatMethod(Method method) {
        StringBuilder sb = new StringBuilder();
        sb.append(formatClassName(method.getReturnType())).append(" ").append(formatClassName(method.getDeclaringClass())).append(".")
                .append(method.getName()).append("(");
        Class<?>[] parameterTypes = method.getParameterTypes();
        int max = parameterTypes.length - 1;
        for (int i = 0; i <= max; i++) {
            sb.append(formatClassName(parameterTypes[i]));
            if (i != max) {
                sb.append(", ");
            }
        }
        return sb.append(")").toString();
    }

    /**
     * Formata uma classe, removendo o nome do pacote
     * 
     * @param cls the class to format
     * @return {@link String}
     */
    public static String formatClassName(Class<?> cls) {
        final String name = cls.getCanonicalName();
        if (name.contains(".")) {
            return name.substring(name.lastIndexOf('.') + 1);
        }
        return cls.getCanonicalName();
    }

}
